#include <Windows.h>
#include <string.h>
//#include <winsock2.h>

#define MSG_WAITALL 0x8

#include "debug.h"

#include "net.h"

const char *LOCALHOST = "127.0.0.1";
const unsigned int DEFAULT_PORT = 5000;

CSrvCon::CSrvCon()
{
	WSADATA wsaData;
	
	if(WSAStartup(MAKEWORD(2,2),&wsaData))
		return;

	address = new char[17];

	strcpy(this->address,LOCALHOST);
	this->port = DEFAULT_PORT;
}

CSrvCon::~CSrvCon()
{
	WSACleanup();

	delete [] address;
}

void CSrvCon::set_address(char *addr)
{
	strcpy(this->address,addr);
}

void CSrvCon::set_port(unsigned int port)
{
	this->port = port;
}

int CSrvCon::open_port(void)
{
	int iResult = 0;
	
	/*int on = 1;
	iResult = setsockopt(this->s, SOL_SOCKET,  SO_REUSEADDR,
                   (char *)&on, sizeof(on));*/

	this->s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if(this->s == SOCKET_ERROR)
	{
		return 0;
	}
	
	/*UINT mode = 0;
	ioctlsocket(this->s, FIONBIO, (u_long *)&mode);*/

	sa.sin_addr.S_un.S_addr = inet_addr(this->address);
	sa.sin_family = AF_INET;
	sa.sin_port = htons(this->port);

	iResult = bind(this->s,(SOCKADDR *) &this->sa,sizeof(sa));
	if(iResult == INVALID_SOCKET)
	{
		closesocket(this->s);
		return 0;
	}

	iResult = listen(this->s,SOMAXCONN);
	if(iResult == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

int CSrvCon::accept_connection()
{
	int size = sizeof(sockaddr_in);

	this->s_clt = accept(this->s,(SOCKADDR*)&sa_clt,&size);
	if(this->s_clt == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

void CSrvCon::close_port()
{
	closesocket(this->s);
}

void CSrvCon::shutdown_client(SOCKET dst_s)
{
	if(!dst_s)
		dst_s = this->s_clt;
	if(shutdown(dst_s,2) == SOCKET_ERROR)
		return;

	closesocket(this->s_clt);
}

int CSrvCon::send_data(char *buf,int size_buf)
{
	int iResult = 0;

	iResult = send(this->s_clt, buf, size_buf,0);
	if(iResult == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

int CSrvCon::send_data_to(SOCKET dst_s, char *buf, int size_buf)
{
	int iResult = 0;

	iResult = send(dst_s, buf, size_buf,0);
	if(iResult == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

int CSrvCon::recv_data(char *buf, int size_buf)
{
	int iResult = 0;

	iResult = recv(this->s_clt, buf, size_buf, 0);
	if(iResult == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

int CSrvCon::recv_data_from(SOCKET src_s, char *buf, int size_buf)
{
	int iResult = 0, offset = 0;

	memset(buf, 0, size_buf);

	iResult = recv(src_s, buf, size_buf, MSG_PEEK);
	if(iResult == 0)
		return 0;

	iResult = recv(src_s, buf, iResult, 0);

	if(iResult == SOCKET_ERROR)
	{
		closesocket(this->s);
		return 0;
	}

	return 1;
}

SOCKET CSrvCon::get_clt_socket()
{
	return s_clt;
}

SOCKET CSrvCon::get_srv_socket()
{
	return s;
}